package com.yutel.telecom.h2;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 建立和网关的socket连接
 * 
 */
public class H2Socket {

	protected static Logger logger = LoggerFactory.getLogger(H2Socket.class);

	/**
	 * H2主机地址监听端口
	 */
	private static final String HOST = "127.0.0.1";
	private static final int PORT = 9000;

	/**
	 * 建立起的socket端
	 */
	private Socket socket;

	/**
	 * 输出流
	 */
	private OutputStream os;

	/**
	 * 输入流
	 */
	private DataInputStream is;

	/**
	 * 构造函数
	 * 
	 * @param host
	 *            H2主机地址
	 * @param port
	 *            监听端口
	 */
	public H2Socket() throws H2Exception {
		initialSock();
	}

	/**
	 * 得到输入流
	 * 
	 * @return DataInputStream
	 */
	public DataInputStream getInputStream() {
		return this.is;
	}

	public OutputStream getOutputStream() {
		return this.os;
	}

	/**
	 * 初始化socket连接,设定超时时间为5秒 <br>
	 * 使用cmpp协议各命令之前,必须调用此方法
	 * 
	 * @throws CMPPException
	 *             封装连接时抛出的UnknownHostException以及IOException
	 */
	private void initialSock() throws H2Exception {
		try {
			if (socket == null) {
				socket = new Socket(HOST, PORT);
			}
			socket.setSoTimeout(30 * 1000);
			// socket.setSoLinger(true,0);
			os = socket.getOutputStream();
			is = new DataInputStream(socket.getInputStream());
			logger.info("成功建立起和H2的socket连接");
		} catch (UnknownHostException e) {
			logger.error("地址\"" + HOST + "\"未知" + e.toString());
			throw new H2Exception("UnknownHostException:" + e.getMessage());
		} catch (IOException e) {
			logger.error("建立socket IO异常:" + e.toString());
			throw new H2Exception("IOException:" + e.getMessage());
		}
	}

	/**
	 * 关闭socket连接
	 * 
	 * @throws CMPPException
	 *             封装关闭连接时抛出的IOException
	 */
	public void closeSock() throws H2Exception {
		try {
			if (socket != null) {
				socket.close();
				if (os != null)
					os.close();
				if (is != null)
					is.close();
			}
			socket = null;
			os = null;
			is = null;
			logger.info("socket连接关闭成功");
		} catch (IOException e) {
			logger.error("socket关闭异常:" + e.toString());
			throw new H2Exception("IOException:" + e.getMessage());
		}
	}

	/**
	 * socket连接上读取输入流
	 * 
	 * @return 输入流的字节形式
	 * @throws IOException
	 */
	public byte[] read(H2Message message) throws H2Exception {
		try {
			byte[] _head = new byte[7];
			int reads = -1;
			// 应该这样读,先读7个字节,其中前2个字节为版本号信息，后5位为数据包大小
			reads = is.read(_head, 0, 7);
			// 没有读到的话
			if (reads == -1) {
				throw new H2Exception("读包头时输入流已空,没有读到数据!");
			}
			byte[] a0 = new byte[2];
			System.arraycopy(_head, 0, a0, 0, 2);
			message.setA0(new String(a0));
			byte[] headlen = new byte[5];
			message.setA1(new String(headlen));
			System.arraycopy(_head, 2, headlen, 0, 5);
			int packetlen = Integer.parseInt(new String(headlen).trim());
			logger.debug("包体长度:::" + packetlen);
			byte[] packet = new byte[packetlen];
			if (packetlen > 0) {
				int size = is.read(packet);
				logger.info("本次输入流读取完毕,预计长度=" + packetlen + ",实际长度:"
						+ (size + 7));
			}
			return packet;
		} catch (IOException e) {
			throw new H2Exception("读包错误:" + e.getMessage());
		}
	}
}